using System;
using System.Collections;
using System.Collections.Generic;

using FineCollection.Intf;




namespace FineCollection.NNative
{
    /// <summary>
    /// Wrapper for a .Net native <see cref="Dictionary{K,P}"/> for use it as a set.
    /// </summary>
    public class NnArrayList<T> : RSet<T>
    {
        /// <summary>
        /// The storage. Bool values are not used.
        /// </summary>
        private readonly Dictionary<T, bool> Dict = 
            new Dictionary<T, bool>();


        /// <summary>
        /// Count of items in the list.
        /// </summary>
        public int Count
        {
            get { return Dict.Count; }
        }

        /// <summary>
        /// Checks whether the collection is empty.
        /// </summary>
        public bool IsEmpty
        {
            get { return Dict.Count == 0; }
        }

        /// <summary>
        /// Checks whether the collection has at least one item.
        /// </summary>
        public bool IsNotEmpty
        {
            get { return Dict.Count > 0; }
        }


        /// <summary>
        /// Checks whether this set contains the specified item.
        /// </summary>
        /// <para>
        /// Complexity of this function is close to <b>O(1)</b>.
        /// </para>
        /// <param name="item">the item to check.</param>
        /// <returns>true - the specified item is in the set.</returns>
        public bool Contains(T item)
        {
            return Dict.ContainsKey(item);
        }


        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return Dict.Keys.GetEnumerator();
        }


        IEnumerator IEnumerable.GetEnumerator()
        {
            return Dict.Keys.GetEnumerator();
        }


        /// <summary>
        /// Creates and returns a read-only iterator.
        /// </summary>
        /// <returns>just created iterator.</returns>
        public RIterator<T> TakeIterator()
        {
            IEnumerator<T> ie = Dict.Keys.GetEnumerator();
            return new Iterator<T>(ie, -1);
        }



        private class Iterator<TT> : RIterator<TT>
        {
            private readonly IEnumerator<TT> ie;
            private sbyte where;


            internal Iterator(IEnumerator<TT> ie, sbyte where)
            {
                this.ie = ie;
                this.where = where;
            }


            /// <summary>
            /// Resets this iterator.
            /// <para>
            /// Initially, iterator points to "begin" state - "before" the first item.
            /// </para>
            /// </summary>
            public void Reset()
            {
                ie.Reset();
                where = -1;
            }


            /// <summary>
            /// Moves to the next element.
            /// </summary>
            /// <returns>"true" if the pointer has moved to the next item,
            ///          "false" if it has moved to behind of all items.</returns>
            public bool Next()
            {
                bool ok = ie.MoveNext();
                where = ok ? (sbyte)0 : (sbyte)+1;
                return ok;
            }


            /// <summary>
            /// The current item (read-only access).
            /// </summary>
            public TT Current
            {
                get { return ie.Current; }
            }

            /// <summary>
            /// Represents where the current position of the iterator.
            /// </summary>
            /// <remarks>
            /// Possible value:
            /// <list type="bullet">
            /// <item>-1: before the first item;</item>
            /// <item>0: at an item of the collection;</item>
            /// <item>+1: behind the last item.</item>
            /// </list>
            /// </remarks>
            public sbyte Where
            {
                get { return where; }
            }


            /// <summary>
            /// Clones the iterator.
            /// </summary>
            /// <returns>an exact </returns>
            public RIterator<TT> Clone()
            {
                throw new NotImplementedException(
                    "Microsoft IEnumerator doesn't support Clone.");
            }
        }
    }
}